package com.xiaochong.bitong.api.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ctc.wstx.util.DataUtil;
import com.netflix.discovery.converters.Auto;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.bitong.api.component.RedisCacheComponent;
import com.xiaochong.bitong.api.config.hbase.HbaseBaseQueryComponent;
import com.xiaochong.bitong.api.constant.ReturnCode;
import com.xiaochong.bitong.api.utils.ListSortPageUtil;
import com.xiaochong.bitong.api.utils.ListSortUtil;
import com.xiaochong.bitong.api.utils.StringUtil;
import com.xiaochong.service.common.config.redis.RedisServer;

import com.xiaochong.tir.common.data.hbasepo.*;
import com.xiaochong.tir.common.data.mapper.*;
import com.xiaochong.tir.common.data.po.*;
import com.xiaochong.tir.common.data.redisPo.CoinPriceVo;
import com.xiaochong.tir.common.data.redisPo.KActionTotalPo;
import com.xiaochong.tir.common.data.vo.*;
import com.xiaochong.tir.common.data.vo.app.MarketIndexVo;
import com.xiaochong.tir.common.exception.hbase.HbaseCloseExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseConnectionExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseGetTableExcetion;
import com.xiaochong.tir.common.util.*;
import jdk.nashorn.internal.ir.ReturnNode;
import org.apache.avro.data.Json;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Semaphore;

/**
 * 此类为[基础代码]自动生成,已经拥有基本的增删改成操作
 * <其他请自行扩展>
 * @author mengxiangdong
 * @time 2018-05-23 14:07
 *
 */
@Service
public class CurrencyService {

    @Autowired
    private RedisServer redisServer;

    @Autowired
    private CurrencyInfoMapper currencyInfoMapper;

    @Autowired
    private CurrencyIndustryCategoryMapper currencyIndustryCategoryMapper;

    @Autowired
    private HbaseBaseQueryComponent hbaseBaseQueryComponent;

    @Autowired
    private ConceptCategoryMapper conceptCategoryMapper;

    @Autowired
    private ExchangeInfoMapper exchangeInfoMapper;

    @Autowired
    CoinSummarizeAffiliatedMapper coinSummarizeAffiliatedMapper;

    @Autowired
    CurrencyInfoHbaseMapper currencyInfoHbaseMapper;

    @Autowired
    ExchangeTransactionpairMiddleMapper exchangeTransactionpairMiddleMapper;

    @Autowired
    private RedisCacheComponent redisCacheComponent;

    @Autowired
    private FundsFlowMapper fundsFlowMapper;

    private static Semaphore semaphore = new Semaphore(1);

    /**
     * 货币行情
     * @return List<T>
     */
    public ApiResultVo getCurrencyQuotation(CurrencyQuotationVo currencyQuotationVo) {
        ApiResultVo resultVo=new ApiResultVo();
        try {
            List<CurrencyQuotationResultVo> quotationList=new ArrayList<>(  );
            String CURRENCY_LIST_APP = redisServer.get( RedisKeyApp.CURRENCY_LIST_APP );
            if(StringUtils.isNotBlank( CURRENCY_LIST_APP )){
                quotationList = JSON.parseArray( CURRENCY_LIST_APP,CurrencyQuotationResultVo.class );
            }else {
                CurrencyInfo currencyInfo = new CurrencyInfo();
                currencyInfo.setEnableFlag( true );
                currencyInfo.setDeleteFlag( false );
                List<CurrencyInfo> currencyList = currencyInfoMapper.selectByEntityList( currencyInfo );

                for (int i = 0; i < currencyList.size(); i++) {
                    CurrencyInfo info = currencyList.get( i );
                    if (!StringUtils.isEmpty( info.getCmcId() )) {
                        CurrencyQuotationResultVo currencyQuotationResultVo = getCurrencyByCmcId( info.getCmcId() );
                        ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
                        exchangeTransactionpairMiddle.setCurrencyId( Integer.valueOf( currencyQuotationResultVo.getId() ) );
                        List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
                        if(ExchangeTransactionpairMiddleList.size()>0){
                            CoinPriceVo coinPriceVo = getNewPrice( currencyQuotationResultVo.getCmcId() );
                            if (currencyQuotationResultVo != null && coinPriceVo!=null) {
                                if (StringUtils.isNotBlank( coinPriceVo.getPriceCny() )) {
                                    currencyQuotationResultVo.setPriceCny( StringUtil.getConverCut( ( coinPriceVo.getPriceCny() )).doubleValue() );
                                    currencyQuotationResultVo.setLastOpenPrice(StringUtil.getConverCut( coinPriceVo.getPriceUsd())+"" );
                                }
                                if (coinPriceVo.getChang24h() != null) {
                                    currencyQuotationResultVo.setChange24h( Double.parseDouble( coinPriceVo.getChang24h() ) );
                                }
                            }
                        }
                        quotationList.add( currencyQuotationResultVo );
                    }
                }
        }
            if (quotationList.size() == 0) {
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
                resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
                return resultVo;
            }

            if(StringUtils.isNotBlank( currencyQuotationVo.getField() )&&StringUtils.isNotBlank(currencyQuotationVo.getType())){
                //排序
                ListSortUtil util=new ListSortUtil();
                util.mySort( quotationList, currencyQuotationVo.getField().trim(), currencyQuotationVo.getType().trim() );
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setData(quotationList);
            resultVo.setPages(currencyQuotationVo.getPageSize());
            resultVo.setTotal(quotationList.size());
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("货币行情",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            return  resultVo;
        }
    }

    public CurrencyQuotationResultVo getCurrencyByCmcId(String cmcId) {
        if(StringUtils.isEmpty(cmcId)){ return null;}
        /**
         * 实时的交易所数据
         */
        return getCurrencyByCmcIdAndUserToken(cmcId);
    }

    /**
     * 根据cmcid
     * @param cmcId
     * @return
     */
    public CurrencyQuotationResultVo getCurrencyByCmcIdAndUserToken(String cmcId) {
        if(StringUtils.isEmpty(cmcId)) return null;

        String redisCacheKey =  RedisKeysUtils.CURRENCY_MARKET+cmcId;

        String result=redisServer.get( redisCacheKey);
        if (result!=null){
            CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( result,CurrencyQuotationResultVo.class );
            return currencyQuotationResultVo;
        }
       return null;
    }


    /**
     * 权重指数
     * @param type
     * @return
     */
    public ApiResultVo<ApiWeightIndexVo> getWeightIndex() {
        Long start = System.currentTimeMillis();
        ApiResultVo<ApiWeightIndexVo> resultVo = new ApiResultVo<>();
        ApiWeightIndexVo voList = new ApiWeightIndexVo();
        resultVo.setDataStamp(System.currentTimeMillis());
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());
        ChartVo chartVo = new ChartVo();
        List<String> x = new LinkedList<>();
        List<String> y = new LinkedList<>();
        try {
                String grailIndex = redisServer.get(RedisKeysUtils.TIR_WEIGHT_INDEX);
                if(org.apache.commons.lang3.StringUtils.isNotBlank(grailIndex)){
                    WeightIndex bi = JSON.parseObject(grailIndex,WeightIndex.class);
                    x.add(String.valueOf(bi.getCreateTime().getTime()));
                    y.add(bi.getWeightIndex()!=null?bi.getWeightIndex().toString():"");
                    String changWeight =  bi.getWeightRiseFall()!=null?bi.getWeightRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString():"";
                    //去第一条数据
                    voList.setChange(changWeight.toString());
                    voList.setIndex(bi.getWeightIndex()!=null?bi.getWeightIndex().setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                    voList.setDifference( StringUtil.getDoubleTwo( Double.parseDouble( voList.getChange() )*Double.parseDouble( voList.getIndex() )/100 )+"" );
                    chartVo.setX(x);
                    chartVo.setY(y);
                    voList.setChart(chartVo);
                }
            if(x == null || x.size() == 0 || y.size() == 0 || y == null){
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
            }else {
                resultVo.setCode(ReturnCode.SUCCESS);
            }
        }catch (Exception e){
            resultVo.setCode(ReturnCode.ERROR);
            LogTrace.error("权重指数",e);
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            e.printStackTrace();
        }
        resultVo.setData(voList);
        resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
        voList.setTir("币通权重指数");
        Long end = System.currentTimeMillis();
        LogTrace.info("权重指数","耗时",String.valueOf(end-start));
        return resultVo;
    }

    /**
     * 大盘指数
     * @param type
     * @return
     */
    public ApiResultVo getGrailIndex(){
        Long start = System.currentTimeMillis();
        ApiResultVo<ApiMarketIndexVo> resultVo = new ApiResultVo<>();
        ApiMarketIndexVo voList = new ApiMarketIndexVo();
        resultVo.setDataStamp(System.currentTimeMillis());
        resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
        ChartVo chartVo = new ChartVo();
        List<String> x = new LinkedList<>();
        List<String> y = new LinkedList<>();
        voList.setChart(chartVo);
        try {
                String grailIndex = redisServer.get(RedisKeysUtils.TIR_BROADER_INDEX);
                LogTrace.info("大盘指数-从reids获取的数据","返回数据",grailIndex);
                if(org.apache.commons.lang3.StringUtils.isNotBlank(grailIndex)){
                    BroaderIndex bi = JSON.parseObject(grailIndex,BroaderIndex.class);
                    x.add(String.valueOf(bi.getCreateTime().getTime()));
                    y.add(bi.getBroaderIndex().toString());
                    voList.setChange(bi.getBroaderRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString());
                    voList.setIndex(bi.getBroaderIndex().setScale(2,BigDecimal.ROUND_DOWN).toString());
                    voList.setDifference( StringUtil.getDoubleTwo( Double.parseDouble( voList.getChange() )*Double.parseDouble( voList.getIndex() )/100 )+"" );
                    chartVo.setX(x);
                    chartVo.setY(y);
                }
            if(voList != null){
                x = voList.getChart().getX();
                y = (List<String>) voList.getChart().getY();
            }
            if(x == null || x.size() == 0 || y == null || y.size() == 0){
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
            }else {
                resultVo.setCode(ReturnCode.SUCCESS);
            }
            voList.setTir("币通大盘指数");
            resultVo.setData(voList);
            Long end = System.currentTimeMillis();
            LogTrace.info("大盘指数","耗时",String.valueOf(end-start));
            return resultVo;
        }catch (Exception e){
            Long end = System.currentTimeMillis();
            LogTrace.info("大盘指数","耗时",String.valueOf(end-start));
            resultVo.setCode(ReturnCode.ERROR);
            e.printStackTrace();
            LogTrace.error("大盘指数",e);
            return resultVo;
        }

    }

    /**
     * 5分钟组装权重指数放入redis中，缓存5分钟，组装
     * @param voList
     * @throws Exception
     */
    public void MakeWeightIndexToCacheOfCalculation( ApiWeightIndexVo voList) throws  Exception{
        ChartVo chartVo = new ChartVo();
        List<String> x = new LinkedList<>();
        List<String> y = new LinkedList<>();
        //判断今天的小时，判断是否需要昨天的，如果需要计算昨日的日期，
        String keyRow = "";
        //获取当前小时
        String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
        String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
        int hourStrInt = Integer.valueOf(hourStr);
        if(hourStrInt < 12){
            keyRow = DateUtils.getNextDayDateYMD(-1);
        }
        if(StringUtils.isNotBlank(keyRow)){//如果需要获取昨日
            this.getWeightIndexOfData(keyRow,chartVo,false,voList,x,y);
        }
        //获取今日数据
        this.getWeightIndexOfData(DateUtils.getCurrentDateString(),chartVo,true,voList,x,y);
        chartVo.setX(x);
        chartVo.setY(y);
        voList.setChart(chartVo);
        if(x.size() > 0 && y.size() > 0){
            //数据插入到redis中
            redisServer.set(RedisKeyApp.APP_TIR_WEIGHT_INDEX_ALL_DATA,JSON.toJSONString(voList),300L);
        }
    }

    public void getWeightIndexOfData(String rowKey,ChartVo vo,boolean isToday,ApiWeightIndexVo voList,
                                     List<String> x,List<String> y) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        Long hstart = System.currentTimeMillis();
        String grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_NAME
                , HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_FAMILY
                , HbaseTableUtils.CALCULATE_TICKER_QUALIFIER
                , HbaseTableUtils.HOME_INDEX_EVERY_DAY_WEIGHTINDEX_ROWKEY+rowKey);
        LogTrace.info("hbase数据查询","是否存在数据"+rowKey, org.apache.commons.lang3.StringUtils.isBlank(grailStr)?"无数据":"有数据");
        LogTrace.info("权重指数","耗时",String.valueOf(System.currentTimeMillis()-hstart));
        if(StringUtils.isBlank(grailStr)) return;
        List<WeightIndex>  hlist = JSON.parseArray(grailStr,WeightIndex.class);
        if(hlist != null && hlist.size() > 0){
            for (int i=0;i<hlist.size();i++){
                WeightIndex hbi =  (WeightIndex)hlist.get(i);
                if(hbi == null || hbi.getCreateTime() == null || hbi.getWeightIndex()== null){
                    continue;  //内容不完整直接过滤
                }
                //存入十二个小时以内数据
                if(DateUtils.getDaysBetweenTwoHours(new Date(),hbi.getCreateTime())<=12) {
                    //x.add(DateUtils.dateFormatString(hbi.getCreateTime(), DateUtils.format_ymdhm_x));
                    x.add(hbi.getCreateTime()!=null?String.valueOf(hbi.getCreateTime().getTime()):"");
                    y.add(hbi.getWeightIndex()!=null?hbi.getWeightIndex().setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                }
            }
            if(isToday){ //取最后一条数据
                voList.setChange(hlist.get(hlist.size()-1).getWeightRiseFall()!=null?hlist.get(hlist.size()-1).getWeightRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                voList.setIndex(hlist.get(hlist.size()-1).getWeightIndex()!=null?hlist.get(hlist.size()-1).getWeightIndex().setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                voList.setDifference( StringUtil.getDoubleTwo( Double.parseDouble( voList.getChange() )*Double.parseDouble( voList.getIndex() )/100 )+"" );
            }
        }
    }

    public List<ApiIndustryTabInfoVo> getIndustryTabInfo() {
//        resultVo.setTradeId(LogTrace.getTrace().getTraceId());
        List<ApiIndustryTabInfoVo> listvo = new ArrayList<>(  );
        try {
             listvo = currencyIndustryCategoryMapper.selectIndustryTabInfo();
            LogTrace.info("获取行业分类","数据",JSON.toJSONString(listvo));
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("获取行业分类",e);
        }
        return listvo;
    }

    /**
     * 根据id获取行业的指数数据，
     * @param type 等于1代表第一次获取所有数据，否则获取最新数据
     * @param industryId  行业id
     * @return
     */
    public ApiResultVo getAllIndustryIndex(Integer industryId,String industry) {
        String redisCacheKey =  RedisKeyApp.CURRENCY_LIST_APP;
        String result=redisServer.get( redisCacheKey);
        Long start = System.currentTimeMillis();
        ApiResultVo<ApiIndustryIndexVo> resultVo = new ApiResultVo<>();
        ApiIndustryIndexVo voList = new ApiIndustryIndexVo();
        LogTrace.info("行业指数-传参","type-industryId-industry",industryId+"-"+industry);
        resultVo.setDataStamp(System.currentTimeMillis());
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());

        if(industryId == null){
            resultVo.setCode(ApiResultCodeUtils.SYSTEM_NULL.getCode());
            resultVo.setMessage(ApiResultCodeUtils.SYSTEM_NULL.getMsg());
            return resultVo;
        }
        ChartVo chartVo = new ChartVo();
        List<String> x = new LinkedList<>();
        List<ApiChartYValue> y = new LinkedList<>();
        try {
                String grailIndex = redisServer.get(RedisKeysUtils.TIR_INDUSTRY_INDEX+industryId);
                if(StringUtils.isNotBlank(grailIndex)){
                    IndustryIndex bi = JSON.parseObject(grailIndex,IndustryIndex.class);
                    x.add(String.valueOf(bi.getCreateTime().getTime()));
                    ApiChartYValue yValue = new ApiChartYValue();
                    yValue.setValue(bi.getIndustryIndex()!=null?bi.getIndustryIndex().setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                    yValue.setContent2(bi.getIndustryRiseFall()!=null?bi.getIndustryRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                    yValue.setDifference( StringUtil.getDoubleTwo(Double.parseDouble(yValue.getValue())*Double.parseDouble(yValue.getContent2())/100)+"" );
                    y.add(yValue);
                    voList.setChange(StringUtil.getDoubleTwo(bi.getIndustryRiseFall().multiply( new BigDecimal( 100 ) ).doubleValue())+"");
                    voList.setIndex(bi.getIndustryIndex().doubleValue());

                    //计算行业流通市值之和，24小时成交额之和
                    CurrencyInfo currencyInfo = new CurrencyInfo();
                    currencyInfo.setId( industryId );
                    List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrenByIncurrId(currencyInfo);
                    double count=0;
                    double turnover24h=0;
                    List<CurrencyQuotationResultVo> currencyQuotationResultVoList=new ArrayList<>(  );
                    if(result!=null){
                         currencyQuotationResultVoList = JSON.parseArray( result,CurrencyQuotationResultVo.class );
                    }

                    //计算最高涨幅的货币和最低涨幅的货币
                    double height=0;
                    double small=0;
                    String heightSyl=null;
                    String smallSyl=null;
                    if(currencyQuotationResultVoList.size()>0){
                        height=currencyQuotationResultVoList.get( 0 ).getChange24h();
                        small=currencyQuotationResultVoList.get( 0 ).getChange24h();
                        CurrencyInfo info=new CurrencyInfo();
                        info.setCmcId( currencyQuotationResultVoList.get( 0 ).getCmcId() );
                        info = currencyInfoMapper.selectByEntity( info );
                        heightSyl=info.getSymbol();
                        smallSyl=info.getSymbol();
                    }
                    int gainsCurrency=0; //币上涨数
                    int declineCurrency=0; //币下跌数
                    for(int j=0;j<currencyInfoList.size();j++){
                        CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                        for (int k=0;k<currencyQuotationResultVoList.size();k++){
                            CurrencyQuotationResultVo currencyQuotationResultVo = currencyQuotationResultVoList.get( k );
                            if(currencyQuotationResultVo.getCmcId().equals( currencyInfo1.getCmcId() )){
                                count=count+currencyQuotationResultVo.getMarketCapCny();
                                turnover24h=turnover24h+currencyQuotationResultVo.getVolume24h();
                                //找涨幅最高
                                if(currencyQuotationResultVo.getChange24h()>height){
                                    height=currencyQuotationResultVo.getChange24h();
                                    heightSyl=currencyInfo1.getSymbol();
                                }
                                //找涨幅最小
                                if(currencyQuotationResultVo.getChange24h()<small){
                                    small=currencyQuotationResultVo.getChange24h();
                                    smallSyl=currencyInfo1.getSymbol();
                                }
                                if(currencyQuotationResultVo.getChange24h()>0){
                                    gainsCurrency = gainsCurrency+1;
                                }else if(currencyQuotationResultVo.getChange24h()<0){
                                    declineCurrency=declineCurrency+1;
                                }
                            }
                        }
                    }
                    voList.setIndustryMarket( count );
                    voList.setTurnover24h( turnover24h );
                    voList.setHighestRise(heightSyl +" "+ height );
                    voList.setMinimumIncrease( smallSyl +" "+small );
                    voList.setHighSymbol( heightSyl );
                    voList.setHighChange( height +"");
                    voList.setMinSymbol( smallSyl );
                    voList.setMinChange( small+"" );
                    voList.setGainsCurrency( String.valueOf( gainsCurrency ) );
                    voList.setDeclineCurrency( String.valueOf( declineCurrency ) );

                    //换手率
                    if(voList.getIndustryMarket()!=0){
                        voList.setRate24h( String.valueOf(StringUtil.getDoubleTwo(voList.getTurnover24h()/voList.getIndustryMarket()*100 )) );
                    }

                    if(y.size()>0){
                        voList.setDifference( y.get( 0 ).getDifference() );
                    }
                    chartVo.setX(x);
                    chartVo.setY(y);
                    voList.setChart(chartVo);
            }
            resultVo.setData(voList);
            voList.setTir("行业指数");
            voList.setIndustry(industry);
            voList.setIndustryId(industryId);
            if(x.size() == 0  || x == null || y == null || y.size() == 0){
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
            }else{
                resultVo.setCode(ReturnCode.SUCCESS);
            }
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            Long end = System.currentTimeMillis();
            LogTrace.info("行业指数","耗时",String.valueOf(end-start));
            return resultVo;
        }catch (Exception e){
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            e.printStackTrace();
            LogTrace.error("行业指数",e);
            Long end = System.currentTimeMillis();
            LogTrace.info("行业指数","耗时",String.valueOf(end-start));
            return resultVo;
        }
    }

    /**
     * 5分钟组装行业指数放入redis中，缓存5分钟，组装
     * @param voList
     * @throws Exception
     */
    private void MakeIndustryToCacheOfCalculation(ApiIndustryIndexVo voList,int industryId) throws Exception{
        ChartVo chartVo = new ChartVo();
        List<String> x = new LinkedList<>();
        List<ApiChartYValue> y = new LinkedList<>();
        //判断今天的小时，判断是否需要昨天的，如果需要计算昨日的日期，
        String keyRow = "";
        //获取当前小时
        String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
        String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
        int hourStrInt = Integer.valueOf(hourStr);
        if(hourStrInt < 12){
            keyRow = DateUtils.getNextDayDateYMD(-1);
        }
        if(StringUtils.isNotBlank(keyRow)){//如果需要获取昨日
            this.getIndustryChartData(keyRow,chartVo,false,voList,industryId,x,y);
        }
        //获取今日数据
        this.getIndustryChartData(DateUtils.getCurrentDateString(),chartVo,true,voList,industryId,x,y);
        chartVo.setX(x);
        chartVo.setY(y);
        voList.setChart(chartVo);
        if(x == null || x.size() ==0 || y == null || y.size() ==0){
            voList = null;
        }else{
            //数据插入到redis中
            redisServer.set(RedisKeyApp.APP_TIR_INDUSTRY_INDEX_ALL_DATA+industryId,JSON.toJSONString(voList),300L);
        }
    }

    /**
     * 遍历数据找出近12小时行业指数数据
     * @param rowKey hbase列
     * @param vo  图标
     * @param isToday  是否今天
     * @param voList  数据
     * @param industryId id
     * @param x 图标x轴
     * @param y 图标y轴
     * @throws HbaseCloseExcetion
     * @throws IOException
     * @throws HbaseGetTableExcetion
     * @throws HbaseConnectionExcetion
     */
    public void getIndustryChartData(String rowKey,ChartVo vo,boolean isToday,ApiIndustryIndexVo voList,int industryId,
                                     List<String> x,List<ApiChartYValue> y) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {

        String redisCacheKey =  RedisKeyApp.CURRENCY_LIST_APP;
        String result=redisServer.get( redisCacheKey);
        String grailStr = null;
        Long hstart = System.currentTimeMillis();
        grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_NAME
                , HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_FAMILY
                , HbaseTableUtils.CALCULATE_TICKER_QUALIFIER
                , industryId+"@"+rowKey
        );
        LogTrace.info("hbase数据查询","是否存在数据"+rowKey, org.apache.commons.lang3.StringUtils.isBlank(grailStr)?"无数据":"有数据");
        LogTrace.info("行业指数hbase数据查询","耗时",String.valueOf(System.currentTimeMillis()-hstart));
        if(StringUtils.isBlank(grailStr)) return ; //vo
        //循环获取每个行业
        List<IndustryIndex> bil = JSON.parseArray(grailStr,IndustryIndex.class);
        if(bil == null || bil.size() ==0) return;
        ApiChartYValue yValue = null;
        for(int k=0;k<bil.size();k++){
            IndustryIndex bi = bil.get(k);
            if(bi == null || bi.getCreateTime() == null || bi.getIndustryIndex()== null || bi.getIndustryRiseFall()== null){
                continue;  //内容不完整直接过滤
            }
            //存入十二个小时以内数据
            if(DateUtils.getDaysBetweenTwoHours(new Date(),bi.getCreateTime())<=12) {
                // x.add(DateUtils.dateFormatString(bi.getCreateTime(), DateUtils.format_ymdhm_x));
                x.add(String.valueOf(bi.getCreateTime().getTime()));
                yValue = new ApiChartYValue();
                yValue.setValue(bi.getIndustryIndex()!=null?bi.getIndustryIndex().setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                yValue.setContent2(bi.getIndustryRiseFall()!=null?bi.getIndustryRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString():"");
                yValue.setDifference( StringUtil.getDoubleTwo(Double.parseDouble(yValue.getValue())*Double.parseDouble(yValue.getContent2())/100)+"" );
                y.add(yValue);
            }
        }
        //取最后一条数据
        if(isToday){
            voList.setChange(bil.get(bil.size()-1).getIndustryRiseFall().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString());
            voList.setIndex(bil.get(bil.size()-1).getIndustryIndex().setScale(2,BigDecimal.ROUND_DOWN).intValue());

            //计算行业流通市值之和，24小时成交额之和
            CurrencyInfo currencyInfo = new CurrencyInfo();
            currencyInfo.setId( industryId );
            List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrenByIncurrId(currencyInfo);
            double count=0;
            double turnover24h=0;
            List<CurrencyQuotationResultVo> currencyQuotationResultVoList=new ArrayList<>(  );
            if(result!=null){
                currencyQuotationResultVoList = JSON.parseArray( result,CurrencyQuotationResultVo.class );
            }

            //计算最高涨幅的货币和最低涨幅的货币
            double height=0;
            double small=0;
            String heightSyl=null;
            String smallSyl=null;
            if(currencyQuotationResultVoList.size()>0){
                height=currencyQuotationResultVoList.get( 0 ).getChange24h();
                small=currencyQuotationResultVoList.get( 0 ).getChange24h();
                CurrencyInfo info=new CurrencyInfo();
                info.setCmcId( currencyQuotationResultVoList.get( 0 ).getCmcId() );
                info = currencyInfoMapper.selectByEntity( info );
                heightSyl=info.getSymbol();
                smallSyl=info.getSymbol();
            }
            for(int j=0;j<currencyInfoList.size();j++){
                CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                for (int k=0;k<currencyQuotationResultVoList.size();k++){
                    CurrencyQuotationResultVo currencyQuotationResultVo = currencyQuotationResultVoList.get( k );
                    if(currencyQuotationResultVo.getCmcId().equals( currencyInfo1.getCmcId() )){
                        count=count+currencyQuotationResultVo.getMarketCapCny();
                        turnover24h=turnover24h+currencyQuotationResultVo.getVolume24h();
                        //找涨幅最高
                        if(currencyQuotationResultVo.getChange24h()>height){
                            height=currencyQuotationResultVo.getChange24h();
                            heightSyl=currencyInfo1.getSymbol();
                        }
                        //找涨幅最小
                        if(currencyQuotationResultVo.getChange24h()<small){
                            small=currencyQuotationResultVo.getChange24h();
                            smallSyl=currencyInfo1.getSymbol();
                        }
                    }
                }
            }
            voList.setIndustryMarket( count );
            voList.setTurnover24h( turnover24h );
            voList.setHighestRise(heightSyl +" "+ height );
            voList.setMinimumIncrease( smallSyl +" "+small );
        }
    }


    /**
     * 概念行情
     *
     * @param T t
     * @return List<T>
     */
    public ApiResultVo conceptIndex(CurrencyQuotationVo currencyQuotationVo) {
        ApiResultVo resultVo = new ApiResultVo();

        try {
            List<ConceptQuotationVo> conList = new ArrayList<ConceptQuotationVo>();

            //redis
            String APP_CONCEPT_QUOTATIONRESULTVO=redisServer.get( RedisKeyApp.APP_CONCEPT_QUOTATIONRESULTVO);
            if (APP_CONCEPT_QUOTATIONRESULTVO!=null){
                LogTrace.info( "概念行情", "数据来源", "redis");
                conList=JSON.parseArray( APP_CONCEPT_QUOTATIONRESULTVO,ConceptQuotationVo.class );
            }

            ConceptCategory conceptCategory = new ConceptCategory();
            if (APP_CONCEPT_QUOTATIONRESULTVO==null){
                conceptCategory.setEnableFlag(true);
                conceptCategory.setDeleteFlag(false);
                List<ConceptCategory> list = conceptCategoryMapper.selectByEntityList(conceptCategory);

                for (int i = 0; i < list.size(); i++) {
                    ConceptQuotationVo vo = new ConceptQuotationVo();
                    String tirconcepe = redisServer.get(RedisKeysUtils.TIR_CONCEPT_INDEX + list.get(i).getId());
                    if (StringUtils.isNotBlank(tirconcepe)) {
                        ConceptIndex conceptIndex = JSON.parseObject(tirconcepe, ConceptIndex.class);
                        vo.setConceptId(list.get(i).getId()); //概念id
                        if (conceptIndex.getConceptIndex() != null)
                            vo.setQuotesIndex(conceptIndex.getConceptIndex().doubleValue()); //概念指数
                        vo.setConcept(list.get(i).getConceptCategoryName());  //概念分类名称
                        if (conceptIndex.getSumVolume24hCnyPrice() != null)
                            vo.setTurnover24h(StringUtil.getDoubleTwo(conceptIndex.getSumVolume24hCnyPrice().doubleValue())); //24小时成交额
                        if (conceptIndex.getAvgPercentChange24h() != null)
                            vo.setChange(conceptIndex.getAvgPercentChange24h().doubleValue()); //平均涨跌幅
                        if (conceptIndex.getRiseCount() != null) vo.setGainsCurrency(conceptIndex.getRiseCount()); //币上涨数
                        if (conceptIndex.getFallCount() != null) vo.setDeclineCurrency(conceptIndex.getFallCount()); //币下跌数
                        if (conceptIndex.getCount() != null) vo.setTotalCurrency(conceptIndex.getCount()); //币种总数

                        if (conceptIndex.getMaxPercentChange24hInfo() != null) {
                            CmcCurrencyInfo maxInfo = conceptIndex.getMaxPercentChange24hInfo();
                            if (maxInfo.getPercentChange24h() != null) {
                                double max = StringUtil.getDoubleTwo(Double.parseDouble(maxInfo.getPercentChange24h()));
                                vo.setStrongestCurrency(max + "");   //币种表现最强
                                vo.setStrongestSymbol(maxInfo.getSymbol());
                            }
                        }
                        if (conceptIndex.getMinPercentChange24hInfo() != null) {
                            CmcCurrencyInfo minInfo = conceptIndex.getMinPercentChange24hInfo();
                            if (minInfo.getPercentChange24h() != null) {
                                double min = StringUtil.getDoubleTwo(Double.parseDouble(minInfo.getPercentChange24h()));
                                vo.setWeakestCurrency(min + "");    //币种表现最弱
                                vo.setWeakestSymbol(minInfo.getSymbol());
                            }

                        }
                        if (vo.getQuotesIndex() == null) {
                            vo.setQuotesIndex(0.00);
                        }

                        if (vo.getChange() == null) {
                            vo.setChange(0.00);
                        }

                        if (vo.getTurnover24h() == null) {
                            vo.setTurnover24h(0.00);
                        }

                        vo.setDifference( StringUtil.getDoubleTwo(vo.getQuotesIndex()*vo.getChange()/100)+"" );

                        //行业市值
                        CurrencyInfo currencyInfo=new CurrencyInfo();
                        currencyInfo.setId( list.get(i).getId() );
                        double count=0;
                        List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrentId(currencyInfo);
                        for(int j=0;j<currencyInfoList.size();j++){
                            CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                            String CURRENCY_MARKET=redisServer.get( RedisKeysUtils.CURRENCY_MARKET+currencyInfo1.getCmcId());
                            if (CURRENCY_MARKET!=null){
                                CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( CURRENCY_MARKET,CurrencyQuotationResultVo.class );
                                count=count+currencyQuotationResultVo.getMarketCapCny();
                            }
                        }
                        vo.setIndustryMarket( count );

                        //24小时换手率
                        if(vo.getIndustryMarket()!=0){
                            vo.setTurnoverRate( StringUtil.getDoubleTwo( vo.getTurnover24h()/vo.getIndustryMarket()) );
                        }
                        conList.add(vo);
                    }
                }
                //存入redis
                if(conList!=null||conList.size()>0){
                    redisServer.set( RedisKeyApp.APP_CONCEPT_QUOTATIONRESULTVO,JSON.toJSONString( conList ),300L);
                }
            }

            //排序
            ListSortUtil util=new ListSortUtil();
            util.mySort( conList, currencyQuotationVo.getField(), currencyQuotationVo.getType() );
            for (int i = 0; i < conList.size(); i++) {
                conList.get(i).setRank(i + 1);  //排名
            }

            //分页
            Object result=null;
            if(conList.size()>0){
                if(currencyQuotationVo.getPageIndex()==null){
                    currencyQuotationVo.setPageIndex( 1 );
                }
                if(currencyQuotationVo.getPageSize()==null){
                    currencyQuotationVo.setPageSize( 15 );
                }
                result=StringUtil.pageBean( conList, currencyQuotationVo.getPageIndex(),currencyQuotationVo.getPageSize());
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(result);
            resultVo.setPages(currencyQuotationVo.getPageSize());
            resultVo.setTotal(conList.size());
            return resultVo;
        } catch (Exception e) {
            e.printStackTrace();
            LogTrace.error("概念行情", e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return resultVo;
        }
    }

    /**
     * 概念指数详情
     *
     * @param T t
     * @return List<T>
     */
    public ApiResultVo conceptIndexById(int conceptId) {
        ApiResultVo resultVo = new ApiResultVo();

        try {
            List<ConceptQuotationVo> conList = new ArrayList<ConceptQuotationVo>();

            //redis
            String APP_CONCEPT_QUOTATIONRESULTVO=redisServer.get( RedisKeyApp.APP_CONCEPT_QUOTATIONRESULTVO+conceptId);
            if (APP_CONCEPT_QUOTATIONRESULTVO!=null){
                LogTrace.info( "概念指数详情", "数据来源", "redis");
                conList=JSON.parseArray( APP_CONCEPT_QUOTATIONRESULTVO,ConceptQuotationVo.class );
            }

            //hbase
            if (APP_CONCEPT_QUOTATIONRESULTVO==null){
                    ConceptQuotationVo vo = new ConceptQuotationVo();
                List<CurrencyQuotationResultVo> CurrencyList = new ArrayList<>(  );
                    String tirconcepe = redisServer.get(RedisKeysUtils.TIR_CONCEPT_INDEX + conceptId);
                    if (StringUtils.isNotBlank(tirconcepe)) {
                        ConceptIndex conceptIndex = JSON.parseObject(tirconcepe, ConceptIndex.class);
                        vo.setConceptId(conceptId); //概念id
                        if (conceptIndex.getConceptIndex() != null)
                            vo.setQuotesIndex(conceptIndex.getConceptIndex().doubleValue()); //概念指数
                            vo.setConcept(conceptIndex.getConceptCategoryName());  //概念分类名称
                        if (conceptIndex.getSumVolume24hCnyPrice() != null)
                            vo.setTurnover24h(StringUtil.getDoubleTwo(conceptIndex.getSumVolume24hCnyPrice().doubleValue())); //24小时成交额
                        if (conceptIndex.getAvgPercentChange24h() != null)
                            vo.setChange(conceptIndex.getAvgPercentChange24h().doubleValue()); //平均涨跌幅
                        if (conceptIndex.getRiseCount() != null) vo.setGainsCurrency(conceptIndex.getRiseCount()); //币上涨数
                        if (conceptIndex.getFallCount() != null) vo.setDeclineCurrency(conceptIndex.getFallCount()); //币下跌数
                        if (conceptIndex.getCount() != null) vo.setTotalCurrency(conceptIndex.getCount()); //币种总数

                        if (conceptIndex.getMaxPercentChange24hInfo() != null) {
                            CmcCurrencyInfo maxInfo = conceptIndex.getMaxPercentChange24hInfo();
                            if (maxInfo.getPercentChange24h() != null) {
                                double max = StringUtil.getDoubleTwo(Double.parseDouble(maxInfo.getPercentChange24h()));
                                vo.setStrongestCurrency(max + "");   //币种表现最强
                                vo.setStrongestSymbol(maxInfo.getSymbol());
                            }
                        }
                        if (conceptIndex.getMinPercentChange24hInfo() != null) {
                            CmcCurrencyInfo minInfo = conceptIndex.getMinPercentChange24hInfo();
                            if (minInfo.getPercentChange24h() != null) {
                                double min = StringUtil.getDoubleTwo(Double.parseDouble(minInfo.getPercentChange24h()));
                                vo.setWeakestCurrency(min + "");    //币种表现最弱
                                vo.setWeakestSymbol(minInfo.getSymbol());
                            }
                        }
                        if (vo.getQuotesIndex() == null) {
                            vo.setQuotesIndex(0.00);
                        }

                        if (vo.getChange() == null) {
                            vo.setChange(0.00);
                        }

                        if (vo.getTurnover24h() == null) {
                            vo.setTurnover24h(0.00);
                        }

                        vo.setDifference( StringUtil.getDoubleTwo(vo.getQuotesIndex()*vo.getChange()/100)+"" );

                        //行业市值
                        CurrencyInfo currencyInfo=new CurrencyInfo();
                        currencyInfo.setId( conceptId );
                        double count=0;
                        int gainsCurrency=0;
                        int declineCurrency=0;
                        List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrentId(currencyInfo);
                        for(int j=0;j<currencyInfoList.size();j++){
                            CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                            String CURRENCY_MARKET=redisServer.get( RedisKeysUtils.CURRENCY_MARKET+currencyInfo1.getCmcId());
                            if (CURRENCY_MARKET!=null){
                                CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( CURRENCY_MARKET,CurrencyQuotationResultVo.class );
                                count=count+currencyQuotationResultVo.getMarketCapCny();
                                ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
                                exchangeTransactionpairMiddle.setCurrencyId( currencyInfo1.getId() );
                                List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
                                if(ExchangeTransactionpairMiddleList.size()>0){
                                    if(currencyQuotationResultVo!=null){
                                        String priceRedisKey = RedisKeyApp.COIN_PRICE+currencyInfo1.getCmcId();
                                        String priceRedisData = redisServer.get(priceRedisKey);
                                        if(StringUtils.isNotBlank(priceRedisData)){
                                            CoinPriceVo coinPriceVoOld = JSON.parseObject(priceRedisData,CoinPriceVo.class);
                                            String cny = coinPriceVoOld.getPriceCny();
                                            if(StringUtils.isNotBlank( cny )){
                                                currencyQuotationResultVo.setPriceCny( Double.parseDouble( cny ) );
                                            }
                                            currencyQuotationResultVo.setLastOpenPrice( coinPriceVoOld.getPriceUsd() );
                                            if(coinPriceVoOld.getChang24h()!=null){
                                                currencyQuotationResultVo.setChange24h( Double.parseDouble( coinPriceVoOld.getChang24h() ) );
                                            }
                                        }
                                    }
                                }
                                if(currencyQuotationResultVo!=null&&currencyQuotationResultVo.getChange24h()!=null){
                                    if(currencyQuotationResultVo.getChange24h()>0){
                                        gainsCurrency=gainsCurrency+1;
                                    }
                                    if(currencyQuotationResultVo.getChange24h()<0){
                                        declineCurrency=declineCurrency+1;
                                    }
                                }
                                CurrencyList.add( currencyQuotationResultVo );
                            }
                        }
                        vo.setGainsCurrency( gainsCurrency );
                        vo.setDeclineCurrency( declineCurrency );
                        vo.setIndustryMarket( count );
                        vo.setCurrencyList( CurrencyList );

                        //24小时换手率
                        if(vo.getIndustryMarket()!=0){
                            vo.setTurnoverRate( StringUtil.getDoubleTwo( vo.getTurnover24h()/vo.getIndustryMarket()*100) );
                        }
                        conList.add(vo);
                    }
                //存入redis
                if(conList!=null||conList.size()>0){
                    redisServer.set( RedisKeyApp.APP_CONCEPT_QUOTATIONRESULTVO+conceptId,JSON.toJSONString( conList ),300L);
                }
            }

            resultVo.setCode( ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(conList);
            resultVo.setTotal(conList.size());
            return resultVo;
        } catch (Exception e) {
            e.printStackTrace();
            LogTrace.error("概念指数详情", e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return resultVo;
        }
    }



    /**
     * 概念货币列表
     *
     * @param T t
     * @return List<T>
     */
    public ApiResultVo CurrencysByConceptId(Integer conceptId,Integer pageIndex,Integer pageSize,String field,String type) {
        ApiResultVo resultVo = new ApiResultVo();

        try {
            List<CurrencyQuotationResultVo> CurrencyQuotationResultVoList = new ArrayList<>(  );
            CurrencyInfo currencyInfo=new CurrencyInfo();
            currencyInfo.setId( conceptId );
            List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrentId(currencyInfo);
            for(int j=0;j<currencyInfoList.size();j++){
                CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                String CURRENCY_MARKET=redisServer.get( RedisKeysUtils.CURRENCY_MARKET+currencyInfo1.getCmcId());
                if (CURRENCY_MARKET!=null){
                    CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( CURRENCY_MARKET,CurrencyQuotationResultVo.class );
                    ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
                    exchangeTransactionpairMiddle.setCurrencyId( Integer.valueOf( currencyQuotationResultVo.getId()) );
                    List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
                    if(ExchangeTransactionpairMiddleList.size()>0){
                        CoinPriceVo coinPriceVo = getNewPrice(currencyQuotationResultVo.getCmcId());
                        if (currencyQuotationResultVo != null  && coinPriceVo!=null) {
                            if(StringUtils.isNotBlank( coinPriceVo.getPriceCny() )){
                                currencyQuotationResultVo.setPriceCny( StringUtil.getConverCut( coinPriceVo.getPriceCny() ).doubleValue() );
                                currencyQuotationResultVo.setLastOpenPrice( StringUtil.getConverCut(coinPriceVo.getPriceUsd())+"" );
                            }
                            if(coinPriceVo.getChang24h()!=null){
                                currencyQuotationResultVo.setChange24h( Double.parseDouble( coinPriceVo.getChang24h() ) );
                            }
                            if(StringUtils.isNotBlank( coinPriceVo.getPriceCny24H())){
                                currencyQuotationResultVo.setDifference( Double.parseDouble( coinPriceVo.getPriceCny24H()) );
                            }
                        }
                    }
                    CurrencyQuotationResultVoList.add( currencyQuotationResultVo );
                }
            }

            //排序
            ListSortUtil sortUtil = new ListSortUtil();
            sortUtil.mySort( CurrencyQuotationResultVoList,field,type );

            //分页
            if(pageIndex==null){
                pageIndex=1;
            }
            if(pageSize==null){
                pageSize=15;
            }
            Object result= StringUtil.pageBean(CurrencyQuotationResultVoList,pageIndex,pageSize  );

            resultVo.setCode( ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(result);
            resultVo.setTotal(CurrencyQuotationResultVoList.size());
            return resultVo;
        } catch (Exception e) {
            e.printStackTrace();
            LogTrace.error("概念货币列表", e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return resultVo;
        }
    }


    /**
     * 行业货币列表
     *
     * @param T t
     * @return List<T>
     */
    public ApiResultVo CurrencysByIndustryId(Integer conceptId,Integer pageIndex,Integer pageSize,String field,String type) {
        ApiResultVo resultVo = new ApiResultVo();

        try {
            List<CurrencyQuotationResultVo> CurrencyQuotationResultVoList = new ArrayList<>(  );
            CurrencyInfo currencyInfo=new CurrencyInfo();
            currencyInfo.setId( conceptId );
            List<CurrencyInfo> currencyInfoList = currencyInfoMapper.serchByCurrenByIncurrId(currencyInfo);
            for(int j=0;j<currencyInfoList.size();j++){
                CurrencyInfo currencyInfo1 = currencyInfoList.get( j );
                String CURRENCY_MARKET=redisServer.get( RedisKeysUtils.CURRENCY_MARKET+currencyInfo1.getCmcId());
                if (CURRENCY_MARKET!=null){
                    CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( CURRENCY_MARKET,CurrencyQuotationResultVo.class );
                    ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
                    exchangeTransactionpairMiddle.setCurrencyId( Integer.valueOf( currencyQuotationResultVo.getId()) );
                    List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
                    if(ExchangeTransactionpairMiddleList.size()>0){
                        CoinPriceVo coinPriceVo = getNewPrice(currencyQuotationResultVo.getCmcId());
                        if (currencyQuotationResultVo != null  && coinPriceVo!=null) {
                            if(StringUtils.isNotBlank( coinPriceVo.getPriceCny() )){
                                currencyQuotationResultVo.setPriceCny( StringUtil.getConverCut( coinPriceVo.getPriceCny()).doubleValue()  );
                                currencyQuotationResultVo.setLastOpenPrice( StringUtil.getConverCut( coinPriceVo.getPriceUsd())+"" );
                            }
                            if(coinPriceVo.getChang24h()!=null){
                                currencyQuotationResultVo.setChange24h( Double.parseDouble( coinPriceVo.getChang24h() ) );
                            }
                            if(StringUtils.isNotBlank( coinPriceVo.getPriceCny24H())){
                                currencyQuotationResultVo.setDifference( Double.parseDouble( coinPriceVo.getPriceCny24H()) );
                            }
                        }
                    }
                    CurrencyQuotationResultVoList.add( currencyQuotationResultVo );
                }
            }

            //排序
            ListSortUtil sortUtil = new ListSortUtil();
            sortUtil.mySort( CurrencyQuotationResultVoList,field,type );

            //分页
            if(pageIndex==null){
                pageIndex=1;
            }
            if(pageSize==null){
                pageSize=15;
            }
            Object result= StringUtil.pageBean(CurrencyQuotationResultVoList,pageIndex,pageSize  );

            resultVo.setCode( ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(result);
            resultVo.setTotal(CurrencyQuotationResultVoList.size());
            return resultVo;
        } catch (Exception e) {
            e.printStackTrace();
            LogTrace.error("行业货币列表", e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return resultVo;
        }
    }



    public ApiResultVo<List<ApiKActionQuantizationVo>> kActionQuantizationSearchMarket(kActionQuantizationParamsVo kActionQuantizationParamsVo) {
        Long st = System.currentTimeMillis();
        ApiResultVo<List<ApiKActionQuantizationVo>> resultVo = new ApiResultVo<>();
        resultVo.setDataStamp(System.currentTimeMillis());
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());
        String searchName = kActionQuantizationParamsVo.getSearchName();
        if(StringUtils.isBlank(searchName)){
            resultVo.setCode(ReturnCode.PARAMS_ERROR);
            return resultVo;
        }
        List<ApiKActionQuantizationVo> vo = new ArrayList<>();
        try {
            List<ApiKActionQuantizationVo> allData = new ArrayList<>();
            //查询交易所
            ExchangeInfo exchangeInfo=new ExchangeInfo();
            exchangeInfo.setEnableFlag( true );
            exchangeInfo.setDeleteFlag( false );
            exchangeInfo.setKlineStatus( true );
            List<ExchangeInfo> infoList=exchangeInfoMapper.selectByEntityList( exchangeInfo );
            String redisKeyCom = RedisKeysUtils.API_SERVICE_TRADES_EXCHANGE_SELECT_ALL_DATA+"@";
            String redisKeyExchange;
            String data;
            List<ApiKActionQuantizationVo> exchangeList;
            for(ExchangeInfo exchange : infoList){
                redisKeyExchange = redisKeyCom+"exchange@"+exchange.getId();
                data = redisServer.get(redisKeyExchange);
                if(StringUtils.isNotBlank(data)){
                    exchangeList = JSON.parseArray(data,ApiKActionQuantizationVo.class);
                    //查找所有数据放入allData中
                    if(exchangeList != null && exchangeList.size() > 0){
                        allData.addAll(exchangeList);
                    }
                }
            }
            String query = searchName.toUpperCase();
            //根据查询的字段模糊匹配放入vo中
            for(ApiKActionQuantizationVo quantization:allData){
                if(quantization.getTransactionName().startsWith(query)){
                    vo.add(quantization);
                }

            }

            if(vo == null || vo.size() == 0){
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
                return resultVo;
            }
            //排序--根据排序取出对应的条数对应的页数的数据返回前端
            if(StringUtils.isBlank(kActionQuantizationParamsVo.getSortField())){//设置默认排序字段是当前价格
                kActionQuantizationParamsVo.setSortField("lastOpenPrice");
            }
            if(StringUtils.isBlank(kActionQuantizationParamsVo.getSortType())){//设置默认排序为降序
                kActionQuantizationParamsVo.setSortType("desc");
            }
            ListSortUtil util=new ListSortUtil();
            util.mySort( vo, kActionQuantizationParamsVo.getSortField().trim(), kActionQuantizationParamsVo.getSortType().trim() );
            //排名
            if (vo.size()>0){
                for (int i=0;i<vo.size();i++){
                    ApiKActionQuantizationVo apiKActionQuantizationVo = vo.get( i );
                    apiKActionQuantizationVo.setRank( i+1 );
                }
            }
            //插入分页默认值分页
            if(kActionQuantizationParamsVo.getPageIndex()==null){
                kActionQuantizationParamsVo.setPageIndex( 1 );
            }
            if(kActionQuantizationParamsVo.getPageSize()==null){
                kActionQuantizationParamsVo.setPageSize( 20 );
            }

            List<ApiKActionQuantizationVo> result= ListSortPageUtil.pageBean(vo,kActionQuantizationParamsVo.getPageIndex(),kActionQuantizationParamsVo.getPageSize());

            //计算页数
            int pages = vo.size()/kActionQuantizationParamsVo.getPageSize();
            int yu = vo.size()%kActionQuantizationParamsVo.getPageSize();
            if(yu > 0){
                pages = pages+1;
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
            resultVo.setPages(pages);
            resultVo.setTotal(vo.size());
            resultVo.setData(result);
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("行情k线-市场行情",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
        }
        LogTrace.info("行情k线-市场行情","总耗时",String.valueOf(System.currentTimeMillis()- st));
        return resultVo;
    }

    public ApiResultVo<ProjectOverviewVo> getProjectOverviewByCmcId(String cmcId) {
        ApiResultVo resultVo=new ApiResultVo();
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try {

            Map<String,Object> hashMap = currencyInfoMapper.getCurrencyInfoDetail(cmcId);
            if(hashMap != null){
                ProjectOverviewVo projectOverviewVo = JSON.parseObject(JSON.toJSONString(hashMap) , ProjectOverviewVo.class);


                List<CoinSummarizeAffiliated> list = coinSummarizeAffiliatedMapper.selectBySummarizeId(projectOverviewVo.getCoinSummarizeId());
                projectOverviewVo.setZeAffiliate(list);
                CurrencyInfoHbase currencyInfoHbase = currencyInfoHbaseMapper.getLastOneByCmcId(projectOverviewVo.getCmcId());
                if(currencyInfoHbase != null){
                    Map<String , Object> currencyInfoMap = hbaseBaseQueryComponent.selectData(HbaseTableUtils.CURRENCY_INFO_TABLE_NAME , currencyInfoHbase.getRowKey());
                    if(currencyInfoMap != null && currencyInfoMap.size() > 0){

                        CmcCurrencyInfo cmcCurrencyInfo = JSON.parseObject(JSON.toJSONString(currencyInfoMap), CmcCurrencyInfo.class);

                        projectOverviewVo.setMarketCap(new BigDecimal(cmcCurrencyInfo.getMaxSupply()!=null?cmcCurrencyInfo.getMaxSupply():"0")
                                .multiply(new BigDecimal(cmcCurrencyInfo.getPriceCny())).toString());
                        projectOverviewVo.setCirculatingSupply(cmcCurrencyInfo.getAvailableSupply());
                        projectOverviewVo.setCirculatingMarketCap(new BigDecimal(cmcCurrencyInfo.getAvailableSupply())
                                .multiply(new BigDecimal(cmcCurrencyInfo.getPriceCny())).toString());
                    }
                }
                resultVo.setCode( ReturnCode.SUCCESS);
                resultVo.setData(projectOverviewVo);
            }
            else{
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
                return resultVo;
            }
            return resultVo;
        }catch (Exception e){
            resultVo.setCode(ReturnCode.ERROR);
            LogTrace.error(e.getMessage() , e);
        }

        return resultVo;
    }


    /**
     *
     市场表现
     * @param T t
     * @return List<T>
     */
    public ApiResultVo MarketPer(String cmcId,int type) {
        ApiResultVo resultVo=new ApiResultVo();
        if(StringUtils.isBlank( cmcId )){
            resultVo.setCode(ReturnCode.PARAMS_ERROR);
        }
        String MARkETPER_INDEX=redisServer.get( RedisKeyApp.MARkETPER_INDEX_APP+type+cmcId);
        JSONObject js = JSON.parseObject( MARkETPER_INDEX );

        if (js!=null){
            LogTrace.info("市场表现","数据来源","redis");
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(js);
            LogTrace.info("redis 缓存","redis","市场表现");
            return resultVo;
        }

        try {
            String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
            String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
            int hourStrInt = Integer.valueOf(hourStr);
            MarketPerVo vo = new MarketPerVo();
            vo.setClassify("市场表现");
            vo.setSortId(2);
//            vo.setExplanation("比较货币价格涨跌幅与大盘指数涨跌幅、行业指数涨跌幅的关系，可以看出当前币种相较于整体市场和行业平均是否处于强势地位。");
            List<String> x=new ArrayList<>();
            List<ResultValueVo> y=new ArrayList<>();
            List<ResultValueVo> y1=new ArrayList<>();
            List<ResultValueVo> y2=new ArrayList<>();
            ShiChartVo chartVo=new ShiChartVo();
            Long jStart = System.currentTimeMillis();
            Map<String,String> map=new HashMap<>(  );
            for (int j=0;j<2;j++){
                String rowkey = DateUtils.getNextDayDateYMD(-j);//取rowkey
                map.put( rowkey,rowkey );
            }

            for (String key : map.keySet()) {
                String grailStr = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.CURRENCY_DIAGNOSIS_MARKET_PERFORMANCE_TABLE_NAME
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_MARKET_PERFORMANCE_TABLE_FAMILY
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_MARKET_PERFORMANCE_QUALIFIER
                        , cmcId + "@" + key
                );
                map.put( key,grailStr);
            }

            for (int i = 0; i < type; i++) {
                String nowRowKey = DateUtils.getLastHourDateStrOfDate(i);
                String grailStr=map.get( nowRowKey);
                JSONObject json = JSON.parseObject( grailStr );

                int nowHour = hourStrInt;
                if(hourStrInt == 0){
                    hourStrInt = 23;
                }else{
                    hourStrInt--;
                }
                JSONArray advice = null;

                if (json != null) {
                    advice = (JSONArray) json.getJSONArray( nowHour + "" );
                }

                if (advice != null) {
                    for (int k = advice.size()-1; k >=0; k--) {
                        JSONObject obj = (JSONObject) advice.get( k );
                        if (obj.containsKey( "createTime" )) x.add( obj.get( "createTime" )+"" );
                        ResultValueVo resuVo = new ResultValueVo();
                        if (obj.containsKey( "priceChangeRate" ))resuVo.setValue(StringUtil.getDoubleTwo(  Double.parseDouble( obj.get( "priceChangeRate" ).toString() )*100) );
                        if (obj.containsKey( "comment" ))resuVo.setComment( obj.get( "comment" ).toString()  );
                        y.add( resuVo );
                        ResultValueVo resuVo2=new ResultValueVo();
                        if (obj.containsKey( "comment" ))resuVo2.setComment( obj.get( "comment" ).toString() );
                        if (obj.containsKey( "broaderChangeRate" ))resuVo2.setValue(StringUtil.getDoubleTwo( Double.parseDouble(obj.get( "broaderChangeRate" ).toString()) *100) );
                        y1.add(resuVo2 );
                        ResultValueVo resuVo3=new ResultValueVo();
                        if (obj.containsKey( "comment" ))resuVo3.setComment( obj.get( "comment" ).toString() );
                        if(obj.containsKey( "industryChangeRate" ))resuVo3.setValue(StringUtil.getDoubleTwo( Double.parseDouble(obj.get( "industryChangeRate" ).toString()) *100) );
                        y2.add( resuVo3);
                        chartVo.setX( x );
                        chartVo.setY( y );
                        chartVo.setY1( y1 );
                        chartVo.setY2( y2 );

                    }
                }
            }
            LogTrace.info("市场表现X轴size","X轴",x.size()+"");
            LogTrace.info("市场表现hbase查询","耗时",String.valueOf(System.currentTimeMillis()-jStart));
            vo.setChart(chartVo);
            vo.setCmcId( cmcId );
            Collections.reverse(x);
            Collections.reverse(y);
            Collections.reverse(y1);
            Collections.reverse(y2);
            if(x.size()>0){
                vo.setTime( x.get( x.size()-1 ) );
            }
            if(y.size()>0){
                vo.setChange(y.get( y.size()-1 ).getValue());
            }
            if(y1.size()>0){
                vo.setMarketChange(y1.get( y1.size()-1 ).getValue());
            }
            if(y2.size()>0){
                vo.setAverageIndustryIndex(y2.get( y2.size()-1 ).getValue());
                vo.setExplanation(y2.get( y2.size()-1 ).getComment());
            }

            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(vo);

            redisServer.set( RedisKeyApp.MARkETPER_INDEX_APP+type+cmcId,JSON.toJSONString( vo ),300L);

            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("市场表现",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }


    /**
     *
     压力支撑
     * @param T t
     * @return List<T>
     */
    public ApiResultVo PressureSup(String cmcId,int type){
        ApiResultVo resultVo=new ApiResultVo();

        String PRESSURE_SUP_INDEX=redisServer.get( RedisKeyApp.PRESSURE_SUP_INDEX_APP+type+cmcId );

        if(StringUtils.isNotBlank( PRESSURE_SUP_INDEX )){
            JSONObject js=JSON.parseObject( PRESSURE_SUP_INDEX );
            if (js!=null){
                LogTrace.info("压力支撑","数据来源","redis");
                resultVo.setCode(ReturnCode.SUCCESS);
                resultVo.setTradeId(LogTrace.getTrace().getTraceId());
                resultVo.setData(js);
                return resultVo;
            }
        }

        try {
            //获取当前小时
            String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
            String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
            int hourStrInt = Integer.valueOf(hourStr);

            PressureSupVo vo = new PressureSupVo();
            vo.setClassify("压力支撑");
            vo.setSortId(3);
//            vo.setExplanation("支撑位是通过黄金分割原理计算出投资者下跌的心理价位，通常是短期下跌反弹位置，如果连续突破多个支撑位，则表明货币短期内可能走弱。");
            List<String> x=new ArrayList<>();
            List<ResultValueVo> y=new ArrayList<>();
            List<ResultValueVo> y1=new ArrayList<>();
            List<ResultValueVo> y2=new ArrayList<>();
            ShiChartVo chartVo=new ShiChartVo();
            Long jStart = System.currentTimeMillis();
            Map<String,String> map=new HashMap<>(  );
            for (int j=0;j<2;j++){
                String rowkey = DateUtils.getNextDayDateYMD(-j);//取rowkey
                map.put( rowkey,rowkey );
            }
            for (String key : map.keySet()) {
                String grailStr = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.CURRENCY_DIAGNOSIS_PRESSURE_SUPPORT_TABLE_NAME
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_PRESSURE_SUPPORT_TABLE_FAMILY
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_PRESSURE_SUPPORT_QUALIFIER
                        , cmcId + "@" + key

                );
                map.put( key,grailStr);
            }

            for (int i=0;i<type;i++){
                String nowRowKey = DateUtils.getLastHourDateStrOfDate(i);
                String grailStr=map.get( nowRowKey);
                JSONObject json = JSON.parseObject( grailStr );

                int nowHour = hourStrInt;
                if(hourStrInt == 0){
                    hourStrInt = 23;
                }else{
                    hourStrInt--;
                }
                JSONArray advice = null;

                if (json != null) {
                    advice = (JSONArray) json.getJSONArray( nowHour + "" );
                }

                if (advice != null) {
                    JSONObject jsonObject = (JSONObject) advice.get(advice.size()-1);
                    if (jsonObject.containsKey("createTime"))vo.setTime(jsonObject.get("createTime").toString());

                    for(int k = advice.size()-1; k >=0; k--){
                        JSONObject obj = (JSONObject) advice.get(k);
                        if (obj.containsKey("createTime"))x.add(obj.get("createTime").toString());
                        ResultValueVo resuVo=new ResultValueVo();
                        if (obj.containsKey("priceCny"))resuVo.setValue( StringUtil.getDoubleTwo( Double.parseDouble(obj.get("priceCny").toString())) );
                        if (obj.containsKey("comment"))resuVo.setComment( obj.get("comment").toString());
                        y.add( resuVo );
                        ResultValueVo resuVo2=new ResultValueVo();
                        if (obj.containsKey("comment"))resuVo2.setComment( obj.get("comment").toString());
                        if (obj.containsKey("emotionalPressure"))resuVo2.setValue(StringUtil.getDoubleTwo( Double.parseDouble(obj.get("emotionalPressure").toString())));
                        y1.add( resuVo2 );
                        ResultValueVo resuVo3=new ResultValueVo();
                        if (obj.containsKey("comment"))resuVo3.setComment( obj.get("comment").toString());
                        if (obj.containsKey("marketSupport"))resuVo3.setValue( StringUtil.getDoubleTwo(Double.parseDouble(obj.get("marketSupport").toString())));
                        y2.add(resuVo3);
                        chartVo.setX(x);
                        chartVo.setY(y);
                        chartVo.setY1(y1);
                        chartVo.setY2(y2);
                    }
                }
            }
            vo.setChart(chartVo);
            vo.setCmcId( cmcId );
            LogTrace.info("压力支撑hbase查询","耗时",String.valueOf(System.currentTimeMillis()-jStart));

            Collections.reverse(x);
            Collections.reverse(y);
            Collections.reverse(y1);
            Collections.reverse(y2);
            if(x.size()>0){
                vo.setTime( x.get( x.size()-1 ) );
            }
            if(y.size()>0){
                vo.setChange(y.get( y.size()-1 ).getValue());
            }
            if(y1.size()>0){
                vo.setPressure(y1.get( y1.size()-1 ).getValue());
            }
            if(y2.size()>0){
                vo.setExplanation(y2.get( y2.size()-1 ).getComment());
                vo.setSupport(y2.get( y2.size()-1 ).getValue());
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(vo);

            redisServer.set( RedisKeyApp.PRESSURE_SUP_INDEX_APP+type+cmcId,JSON.toJSONString( vo ),300L);
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("压力支撑",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }


    /**
     *
     平均成本
     * @param T t
     * @return List<T>
     */
    public ApiResultVo avgCost(String cmcId,int type){
        ApiResultVo resultVo=new ApiResultVo();
        Long jStart = System.currentTimeMillis();

        String AVG_COST_INDEX=redisServer.get( RedisKeyApp.AVG_COST_INDEX_APP+type+cmcId );
        if(StringUtils.isNotBlank( AVG_COST_INDEX )){
            JSONObject   js=JSON.parseObject( AVG_COST_INDEX );

            if (js!=null){
                LogTrace.info("平均成本","数据来源","redis");
                resultVo.setCode(ReturnCode.SUCCESS);
                resultVo.setTradeId(LogTrace.getTrace().getTraceId());
                resultVo.setData(js);
                LogTrace.info("redis 缓存","redis","js2");
                return resultVo;
            }
        }

        try {
            String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
            String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
            int hourStrInt = Integer.valueOf(hourStr);

            AvgCostVo vo = new AvgCostVo();

            vo.setClassify("平均成本");
            vo.setSortId(1);
//            vo.setExplanation("计算近一个小时的移动平均价格，通过分析现时价格与平均成本的关系，可以看出近期交易的投资者整体是盈利还是亏损。");
            List<String> x=new ArrayList<>();
            List<ResultValueVo> y=new ArrayList<>();
            List<ResultValueVo> y1=new ArrayList<>();
            AvgChartVo chartVo=new AvgChartVo();
            Map<String,String> map=new HashMap<>(  );
            for (int j=0;j<2;j++){
                String rowkey = DateUtils.getNextDayDateYMD(-j);//取rowkey
                map.put( rowkey,rowkey );
            }

            for (String key : map.keySet()) {
                String grailStr = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.CURRENCY_DIAGNOSIS_AVERAGE_COST_INFO_TABLE_NAME
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_AVERAGE_COST_INFO_TABLE_FAMILY
                        , HbaseTableUtils.CURRENCY_DIAGNOSIS_AVERAGE_COST_INFO_QUALIFIER
                        , cmcId + "@" + key
                );
                map.put( key,grailStr);
                LogTrace.info( "平均成本...",key, grailStr!=null?"1":"0");
            }

            for (int j = 0; j < type; j++) {
                String nowRowKey = DateUtils.getLastHourDateStrOfDate(j);
                String grailStr=map.get( nowRowKey);
                JSONObject json = JSON.parseObject( grailStr );

                int nowHour = hourStrInt;
                if(hourStrInt == 0){
                    hourStrInt = 23;
                }else{
                    hourStrInt--;
                }
                JSONArray advice = null;

                if (json != null) {
                    advice = (JSONArray) json.getJSONArray( nowHour + "" );
                }
                if (advice != null) {
                    for (int k = advice.size()-1; k >=0; k--) {
                        JSONObject obj = (JSONObject) advice.get( k );
                        if (obj.containsKey( "createTime" )) x.add( obj.get( "createTime" ).toString() );

                        ResultValueVo resuVo=new ResultValueVo();
                        if (obj.containsKey( "priceCny" ))resuVo.setValue( StringUtil.getDoubleTwo( Double.parseDouble( obj.get( "priceCny" ).toString()) ) );
                        if (obj.containsKey( "comment" ))resuVo.setComment(  obj.get( "comment" ).toString()  );
                        y.add( resuVo );

                        ResultValueVo resuVo2=new ResultValueVo();
                        if (obj.containsKey( "comment" ))resuVo2.setComment(obj.get( "comment" ).toString() );
                        if (obj.containsKey( "diagnosisAverageCost" ))resuVo2.setValue( StringUtil.getDoubleTwo(Double.parseDouble( obj.get( "diagnosisAverageCost" ).toString() )) );
                        y1.add( resuVo2 );
                        chartVo.setX( x );
                        chartVo.setY( y );
                        chartVo.setY1( y1 );
                    }
                }
            }
            LogTrace.info("平均成本X轴size","X轴",x.size()+"");

            LogTrace.info("平均成本hbase查询","耗时",String.valueOf(System.currentTimeMillis()-jStart));
            vo.setChart(chartVo);
            vo.setCmcId( cmcId );
            Collections.reverse(x);
            Collections.reverse(y);
            Collections.reverse(y1);
            if(x.size()>0){
                vo.setTime( x.get( x.size()-1 ) );
            }
            if(y.size()>0){
                vo.setPrice( y.get( y.size()-1 ).getValue() );
            }
            if(y1.size()>0){
                vo.setAveragePrice( y1.get( y1.size()-1 ).getValue() );
                vo.setExplanation( y1.get( y1.size()-1 ).getComment() );
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(vo);

            redisServer.set( RedisKeyApp.AVG_COST_INDEX_APP+type+cmcId,JSON.toJSONString( vo ),300L);
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("平均成本",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }


    /**
     *
     多空行情
     * @param T t
     * @return List<T>
     */
    public ApiResultVo spaceTrend(String cmcId,int type){
        ApiResultVo resultVo=new ApiResultVo();
        String SPACETREND_INDEX=redisServer.get( RedisKeyApp.SPACETREND_INDEX_APP+type+cmcId);

        if(StringUtils.isNotBlank( SPACETREND_INDEX )){
            JSONObject  js=JSON.parseObject( SPACETREND_INDEX );
            if (js!=null){
                LogTrace.info("多空行情","数据来源","redis");
                resultVo.setCode(ReturnCode.SUCCESS);
                resultVo.setTradeId(LogTrace.getTrace().getTraceId());
                resultVo.setData(js);
                return resultVo;
            }
        }

        try {
            //获取当前小时
            String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
            String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
            int hourStrInt = Integer.valueOf(hourStr);

            SpaceTrendVo vo = new SpaceTrendVo();
            vo.setClassify("多空行情");
            vo.setSortId(4);
//            vo.setExplanation("当现时价格大于5h平均线和过去24小时平均线时，说明价格突破均线，未来可能继续上涨。当价格跌破均线时，未来可能继续下跌。");
            List<String> x=new ArrayList<>();
            List<ResultValueVo> y=new ArrayList<>();
            List<ResultValueVo> y1=new ArrayList<>();
            List<ResultValueVo> y2=new ArrayList<>();
            ShiChartVo chartVo=new ShiChartVo();
            Long jStart = System.currentTimeMillis();
            Map<String,String> map=new HashMap<>(  );
            for (int j=0;j<2;j++){
                String rowkey = DateUtils.getNextDayDateYMD(-j);//取rowkey
                map.put( rowkey,rowkey );
            }

            for (String key : map.keySet()) {
                String grailStr = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.LONG_AND_SHORT_TREND_TABLE_NAME
                        , HbaseTableUtils.LONG_AND_SHORT_TREND_TABLE_NAME_FAMILY
                        , HbaseTableUtils.LONG_AND_SHORT_TREND_TABLE_NAME_QUALIFIER
                        , cmcId + "@" + key
                );
                map.put( key,grailStr);
            }

            for (int j = 0; j < type; j++) {
                String nowRowKey = DateUtils.getLastHourDateStrOfDate(j);
                String grailStr=map.get( nowRowKey);
                JSONObject json = JSON.parseObject( grailStr );

                int nowHour = hourStrInt;
                if(hourStrInt == 0){
                    hourStrInt = 23;
                }else{
                    hourStrInt--;
                }
                JSONArray advice = null;

                if (json!=null) {
                    advice = (JSONArray) json.getJSONArray(nowHour + "");
                }
                if (advice != null) {
                    for (int k = advice.size()-1; k >=0; k--) {
                        JSONObject obj = (JSONObject) advice.get( k );
                        if (obj.containsKey( "createTime" )) x.add( obj.get( "createTime" ).toString() );

                        ResultValueVo resuVo=new ResultValueVo();
                        if (obj.containsKey( "priceCny" ))resuVo.setValue(StringUtil.getDoubleTwo( Double.parseDouble( obj.get( "priceCny" ).toString() )));
                        if(obj.containsKey( "comment" ))resuVo.setComment( obj.get( "comment" ).toString() );
                        y.add( resuVo);

                        ResultValueVo resuVo2=new ResultValueVo();
                        if (obj.containsKey("comment"))resuVo2.setComment( obj.get("comment").toString());
                        if (obj.containsKey("avg2PriceCny"))resuVo2.setValue(StringUtil.getDoubleTwo( Double.parseDouble( obj.get("avg2PriceCny").toString())));//过去24小时平均价
                        y1.add( resuVo2 );

                        ResultValueVo resuVo3=new ResultValueVo();
                        if (obj.containsKey("comment"))resuVo3.setComment(obj.get("comment").toString());
                        if (obj.containsKey( "avg1PriceCny" ))resuVo3.setValue(StringUtil.getDoubleTwo( Double.parseDouble( obj.get("avg1PriceCny").toString())));//过去5小时平均价
                        y2.add( resuVo3);
                        chartVo.setX( x );
                        chartVo.setY( y );
                        chartVo.setY1( y1 );
                        chartVo.setY2( y2 );
                    }
                }
            }

            LogTrace.info("多空行情hbase查询","耗时",String.valueOf(System.currentTimeMillis()-jStart));
            vo.setChart(chartVo);
            vo.setCmcId( cmcId );
            Collections.reverse(x);
            Collections.reverse(y);
            Collections.reverse(y1);
            Collections.reverse(y2);
            if(x.size()>0){
                vo.setTime( x.get( x.size()-1 ) );
            }
            if(y.size()>0){
                vo.setPrice( y.get( y.size()-1 ).getValue() );
            }
            if(y1.size()>0){
                vo.setPriceBefore3h( y1.get( y1.size()-2 ).getValue() );
            }
            if(y2.size()>0){
                vo.setPriceBefore1h( y2.get(y2.size()-1).getValue() );
                vo.setExplanation( y2.get( y2.size()-1 ).getComment() );
            }
            resultVo.setCode(ReturnCode.SUCCESS);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            resultVo.setData(vo);

            redisServer.set( RedisKeyApp.SPACETREND_INDEX_APP+type+cmcId,JSON.toJSONString( vo ),300L);
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("多空行情",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }


    /**
     *
     平台币概念指数
     * @param T t
     * @return List<T>
     */
    public ApiResultVo bottomteZhi(Integer id,Integer hour,Integer day) {
        ApiResultVo resultVo=new ApiResultVo();
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try {
            String BOTTOMTEZHI_INDEX=redisServer.get( RedisKeyApp.BOTTOMTEZHI_INDEX+day+":"+hour+":"+id );

            if (StringUtils.isNotBlank( BOTTOMTEZHI_INDEX )){
                List<GaiNianZhiShuVo> GaiNianZhiShuVoList = JSON.parseArray( BOTTOMTEZHI_INDEX,GaiNianZhiShuVo.class );
                LogTrace.info("平台币概念指数","redis",null);
                resultVo.setCode(ReturnCode.SUCCESS);
                resultVo.setData(GaiNianZhiShuVoList);
            }else{
                resultVo.setCode( ReturnCode.DATA_NOT_EXIST );
            }
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("平台币概念指数",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }

    }

    /**
     *
     行业指数
     * @param T t
     * @return List<T>
     */
    public ApiResultVo industryIndex(Integer id,Integer hour,Integer day) {
        ApiResultVo resultVo=new ApiResultVo();
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());
        try {
            String INDUSTRY_INDEX=redisServer.get( RedisKeyApp.INDUSTRY_INDEX+day+":"+hour+":"+id );
            if (StringUtils.isNotBlank( INDUSTRY_INDEX )){
               List<IndustryDataVo> IndustryDataVoLIst = JSON.parseArray(INDUSTRY_INDEX ,IndustryDataVo.class );
                    LogTrace.info("行业指数","redis",null);
                    resultVo.setCode(ReturnCode.SUCCESS);
                    resultVo.setData(IndustryDataVoLIst);
            }else{
                    resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
            }
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("行业指数",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }

    /**
     * 行业指数(列表)
     * @param rowKey
     * @return
     * @throws HbaseConnectionExcetion
     * @throws HbaseGetTableExcetion
     * @throws IOException
     * @throws HbaseCloseExcetion
     */
    private String getBroaderData(String rowKey) throws HbaseConnectionExcetion, HbaseGetTableExcetion, IOException, HbaseCloseExcetion {
        String grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_NAME
                , HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_FAMILY
                , HbaseTableUtils.CALCULATE_TICKER_QUALIFIER
                , rowKey
        );
        LogTrace.info("hbase行业指数查询","是否存在数据"+rowKey, org.apache.commons.lang3.StringUtils.isBlank(grailStr)?"无数据":"有数据");
        return grailStr;
    }

    /**
     *
     货币价格趋势图
     * @param T t
     * @return List<T>
     */
    public ApiResultVo currencyIndex(String cmcId,Integer hour,Integer day) {
        ApiResultVo resultVo=new ApiResultVo();
        resultVo.setTradeId(LogTrace.getTrace().getTraceId());
        try {
            String INDUSTRY_INDEX=redisServer.get( RedisKeyApp.CYRRENCY_INDEX+day+":"+hour+":"+cmcId );
            if (StringUtils.isNotBlank( INDUSTRY_INDEX )){
                List<CurrencyDataVo> CurrencyDataVoList = JSON.parseArray( INDUSTRY_INDEX , CurrencyDataVo.class );
                LogTrace.info("货币价格趋势图","redis",null);
                resultVo.setCode(ReturnCode.SUCCESS);
                resultVo.setData(CurrencyDataVoList);
            }else{
                resultVo.setCode(ReturnCode.DATA_NOT_EXIST);
            }
            return resultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("货币价格趋势图",e);
            resultVo.setCode(ReturnCode.ERROR);
            resultVo.setTradeId(LogTrace.getTrace().getTraceId());
            return  resultVo;
        }
    }

    public ApiResultVo<ChartVo> capitalInflowSituation(String cmcId,String timePartType) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        ApiResultVo apiResultVo = new ApiResultVo();
        apiResultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try{
            CurrencyInfo info = redisCacheComponent.getCurrencyInfo(cmcId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
            exchangeTransactionpairMiddle.setCurrencyId( info.getId() );
            List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
            ChartVo chart1DVo = new ChartVo();
            ChartVo chart3HVo = new ChartVo();
            List<String> x3h = new ArrayList<>();
            List<String> y3h = new ArrayList<>();
            chart3HVo.setX(x3h);
            chart3HVo.setY(y3h);
            List<String> x1d = new ArrayList<>();
            List<String> y1d = new ArrayList<>();
            chart1DVo.setX(x1d);
            chart1DVo.setY(y1d);

            LocalDateTime time = LocalDateTime.now();
            time = time.minusMinutes(10);//当前分钟不要
            String timePart=null;

            BigDecimal flow24h = new BigDecimal( 0 );
            for(int i=0;i<288;i++){
                //循环288次，共24小时,5分钟一条
                int minu = time.getMinute()/5;
                timePart = DateUtils.localDateTimeFormatString(time,DateUtils.format_ymdh);
                timePart += minu < 10 ? "0"+minu:minu;

                BigDecimal flow = new BigDecimal( 0 );
                for(int k=0;k<ExchangeTransactionpairMiddleList.size();k++){
                    exchangeTransactionpairMiddle = ExchangeTransactionpairMiddleList.get( k );
                    int exchangeId=exchangeTransactionpairMiddle.getExchangeId();
                    String transactionName = exchangeTransactionpairMiddle.getTransactionName();
                    String rowKey = HbaseTableUtils.API_SERVICE_TRADES_PART__ROWKEY + "@" + exchangeId + "@" + transactionName + "@" + timePart;
                    String tradesHistory =  getCapitalInflowSituation(rowKey);
                    if(tradesHistory!=null){
                        TradesHistoryCountFive historyCountFive = JSON.parseObject(tradesHistory,TradesHistoryCountFive.class);
                        flow=historyCountFive.getBuyAmount().subtract(historyCountFive.getSellAmount()).add( flow );
                        flow24h=historyCountFive.getBuyAmount().subtract(historyCountFive.getSellAmount()).add( flow24h );
                    }
                }

                if(i < 36){
                    x3h.add(String.valueOf(Timestamp.valueOf(time).getTime()));
                    y3h.add(flow.setScale(2,BigDecimal.ROUND_DOWN).toString());
                }
                x1d.add(String.valueOf(Timestamp.valueOf(time).getTime()));
                y1d.add(flow.setScale(2,BigDecimal.ROUND_DOWN).toString());
                if(timePartType.equals( "3h" )) {
                    time = time.minusMinutes( 5 );
                }else{
                    time = time.minusMinutes( 10 );
                }
            }

            Collections.reverse(x3h);
            Collections.reverse(y3h);
            Collections.reverse(x1d);
            Collections.reverse(y1d);
            if(x3h.size()>0){
                chart3HVo.setCreateTime( x3h.get( x3h.size()-1 ) );
            }
            if(x1d.size()>0){
                chart1DVo.setCreateTime( x1d.get( x1d.size()-1 ) );
            }
            if(timePartType.equals( "3h" )){
                apiResultVo.setData( chart3HVo );
                apiResultVo.setTotal( x3h.size() );
            }else{
                apiResultVo.setData( chart1DVo );
                apiResultVo.setTotal( x1d.size() );
            }

            apiResultVo.setCode(ReturnCode.SUCCESS);
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("资金流入今日3小时、24小时",e);
            apiResultVo.setCode(ReturnCode.ERROR);
            return  apiResultVo;
        }
        return apiResultVo;
    }

    public ApiResultVo<ChartVo> capitalInflowSituationHistogram(String cmcId) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        ApiResultVo apiResultVo = new ApiResultVo();
        apiResultVo.setTradeId(LogTrace.getTrace().getTraceId());
        ChartVo chart1DVo = new ChartVo();
        List<String> x1d = new ArrayList<>();
        List<String> y1d = new ArrayList<>();
        try{
            CurrencyInfo info = redisCacheComponent.getCurrencyInfo(cmcId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
            exchangeTransactionpairMiddle.setCurrencyId( info.getId() );
            List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
            String lastRowKey =null;
            int d=86400000;
            Long nowTImeres = new Date(  ).getTime();
            while (true){
                double fundsOnlyflow=0;
                long now=nowTImeres-d;
                LocalDateTime timeres = DateUtils.getDateTimeOfTimestamp(now);
                lastRowKey = DateUtils.localDateTimeFormatString(timeres,DateUtils.format_ymd);//当前时间转成分钟

                for(int i=0;i<ExchangeTransactionpairMiddleList.size();i++){
                    exchangeTransactionpairMiddle = ExchangeTransactionpairMiddleList.get( i );
                    int exchangeId = exchangeTransactionpairMiddle.getExchangeId();
                    String transactionName = exchangeTransactionpairMiddle.getTransactionName();

                    FundsFlow fundsFlow = new FundsFlow();
                    fundsFlow.setExchangeId( exchangeId );
                    fundsFlow.setTransactionName( transactionName );
                    fundsFlow.setFundsDate( lastRowKey );
                    List<FundsFlow> fundsFlowList = fundsFlowMapper.selectByEntityList( fundsFlow );
                    if(fundsFlowList.size()>0){
                        fundsFlow = fundsFlowList.get( 0 );
                        if(StringUtils.isNotBlank(fundsFlow.getFundsOnlyflow())){
                            fundsOnlyflow=Double.parseDouble( fundsFlow.getFundsOnlyflow() )+fundsOnlyflow;
                        }
                        if(StringUtils.isBlank( chart1DVo.getCreateTime() )){
                            chart1DVo.setCreateTime(DateUtils.dateFormatString(fundsFlow.getCreateTime(),DateUtils.format_ymdhms)+"");
                        }
                    }
                }
                x1d.add( DateUtils.localDateTimeFormatString(timeres,DateUtils.formatm_d) );
                y1d.add( new Double( fundsOnlyflow ).intValue()+"" );

                if(d>345600000){
                    break;
                }
                d+=86400000;
            }

            chart1DVo.setX( x1d );
            chart1DVo.setY( y1d );
//            chart1DVo.setCreateTime( DateUtils.dateFormatString(new Date(  ),DateUtils.format_ymd) );
            Collections.reverse(x1d);
            Collections.reverse(y1d);
            apiResultVo.setData( chart1DVo );
            apiResultVo.setCode(ReturnCode.SUCCESS);
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("资金流入5日柱状图",e);
            apiResultVo.setCode(ReturnCode.ERROR);
            return  apiResultVo;
        }
        return apiResultVo;
    }

    public ApiResultVo<TradesHistoryData> capitalFlowDistribution24H(String cmcId) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        ApiResultVo apiResultVo = new ApiResultVo();
        apiResultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try{
            String CAPITAL_INDEX = redisServer.get( RedisKeyApp.CAPITAL_INDEX+cmcId );
            if(StringUtils.isNotBlank( CAPITAL_INDEX )){
                TradesHistoryData tradesHistoryData = JSON.parseObject( CAPITAL_INDEX , TradesHistoryData.class );
                tradesHistoryData.setCreateTime( new Date(  ) );
                if(tradesHistoryData!=null){
                    LogTrace.info("24H资金流向分布","数据来源","redis");
                    apiResultVo.setData( tradesHistoryData );
                    apiResultVo.setCode(ReturnCode.SUCCESS);
                    return apiResultVo;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("资金流入今日3小时、24小时",e);
            apiResultVo.setCode(ReturnCode.ERROR);
            return  apiResultVo;
        }
        return apiResultVo;
    }

    private String getCapitalInflowSituation(String rowKey) throws HbaseConnectionExcetion, HbaseGetTableExcetion, IOException, HbaseCloseExcetion {
        String tradesHistory =  hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME
                , HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME_FAMILY
                , HbaseTableUtils.API_SERVICE_TRADES_QUALIFIER
                , rowKey
        );
        return tradesHistory;
    }

    public CoinPriceVo getNewPrice(String cmcId){
        String priceRedisKey = RedisKeyApp.COIN_PRICE+cmcId;
        String priceRedisData = redisServer.get(priceRedisKey);
        if(StringUtils.isNotBlank(priceRedisData)) {
            CoinPriceVo coinPriceVoOld = JSON.parseObject( priceRedisData, CoinPriceVo.class );
            return coinPriceVoOld;
        }
        return  null;
    }
}